import { useEffect, useRef } from 'react'
import './RemoveBgModal.scss'
import RemoveSvg from '@/svg/RemoveSvg'
import useStateRef from '@/hooks/useStateRef'
import imageLoadManager from '@/lib/imageLoadManager'
import { loadImageInfo } from '@/utils/loadVideo'
import { showLoading } from '@/utils/loading'
import { Color } from '@/lib/Color'
import { imageFilter } from '@/lib/imageFilter'
import useNumInput from '@/hooks/useNumInput'
import CustomCanvas from '@/component/CustomCanvas'
import { useI18n } from '@/i18n'
import { imageFeathering } from '@/lib/imageFeathering'
interface Props {
  show: boolean
  onHide: () => void
  frameList: FrameInfo[]
  allFrameList: FrameInfo[]
  fps: number
  onUpdate: (frameList: FrameInfo[]) => void
}
const removeMode = [
  {
    value: 0,
    label: 'noTransparency',
  },
  {
    value: 1,
    label: 'translucent',
  },
]
const RemoveBgModal = ({
  show,
  onHide,
  frameList,
  allFrameList,
  fps,
  onUpdate,
}: Props) => {
  const { t } = useI18n()
  const canvasRef = useRef<HTMLCanvasElement>(null)
  const imageFrameList = useRef<HTMLImageElement[]>([])
  const canvasCtx = useRef<CanvasRenderingContext2D | null>(null)
  const [canvasSize, setCanvasSize, canvasSizeRef] = useStateRef({
    width: 200,
    height: 200,
  })
  const [color, setColor, colorRef] = useStateRef('#00ff00')
  const [mode, setMode, modeRef] = useStateRef(0)
  useEffect(() => {
    const task = async () => {
      if (frameList.length != 0) {
        const info = await loadImageInfo(frameList[0].url)
        setCanvasSize({
          width: info.width,
          height: info.height,
        })
        canvasRef.current.width = info.width
        canvasRef.current.height = info.height
      } else {
        setCanvasSize({ width: 200, height: 200 })
        canvasRef.current.width = 200
        canvasRef.current.height = 200
      }
    }
    task()
  }, [frameList])
  useEffect(() => {
    if (!show) {
      return
    }
    let isEnd = false
    const task = async () => {
      imageFrameList.current = await imageLoadManager.loadImageList(frameList)
      //   if (!play) {
      //     return
      //   }
      // 帧时间
      const frameTime = 1000 / fps
      let frame = 0
      let nowframeTime = 0
      let lastTime = 0
      canvasCtx.current = canvasRef.current.getContext('2d')
      canvasCtx.current.imageSmoothingEnabled = false
      const anim = (nowTime: number) => {
        const deltaTime = nowTime - lastTime
        lastTime = nowTime
        nowframeTime += deltaTime
        const addFrame = Math.floor(nowframeTime / frameTime)
        nowframeTime = nowframeTime % frameTime
        draw(frame)
        frame += addFrame
        if (frameList.length == 0) isEnd = true
        while (frame >= frameList.length && frameList.length != 0) {
          frame -= frameList.length
        }
        if (isEnd) return
        requestAnimationFrame(anim)
      }
      requestAnimationFrame(anim)
    }
    task()
    return () => {
      isEnd = true
    }
  }, [show, frameList, canvasSize])
  const filter = (ctx: CanvasRenderingContext2D) => {
    const needRemoveColor = Color.fromHex(colorRef.current)
    const imageData = ctx.getImageData(
      0,
      0,
      canvasSizeRef.current.width,
      canvasSizeRef.current.height,
      {
        colorSpace: 'srgb',
      }
    )
    const v = powerRef.current * 4.4167295593006

    for (let i = 0; i < imageData.data.length; i += 4) {
      const r = imageData.data[i]
      const g = imageData.data[i + 1]
      const b = imageData.data[i + 2]
      const a = imageData.data[i + 3]
      const color = new Color(r, g, b)
      if (a < 5) {
        continue
      }
      if (color.getSimilarity(needRemoveColor) < v) {
        imageData.data[i + 3] = 0
      } else if (modeRef.current == 1) {
        const dr = Math.abs(color.r - needRemoveColor.r)
        const dg = Math.abs(color.g - needRemoveColor.g)
        const db = Math.abs(color.b - needRemoveColor.b)
        const d = Math.max(dr, dg, db)
        if (d < 25) {
          imageData.data[i + 3] = 0
        } else if (d > 175) {
          imageData.data[i + 3] = 255
        } else {
          imageData.data[i + 3] = d
        }
      }
    }
    imageFeathering(
      canvasCtx.current,
      canvasRef.current.width,
      canvasRef.current.height,
      featheringRef.current,
      imageData
    )
    ctx.putImageData(imageData, 0, 0)
  }
  const draw = (frame = 0) => {
    if (frame < 0 || frame >= imageFrameList.current.length) {
      return
    }
    const ctx = canvasCtx.current
    if (!ctx) return
    const w = canvasSizeRef.current.width
    const h = canvasSizeRef.current.height
    ctx.clearRect(0, 0, w, h)
    if (frameList.length == 0) {
      return
    }
    const imageW = imageFrameList.current[frame].naturalWidth
    const imageH = imageFrameList.current[frame].naturalHeight
    ctx.drawImage(
      imageFrameList.current[frame],
      0,
      0,
      imageW,
      imageH,
      0,
      0,
      w,
      h
    )
    filter(ctx)
  }
  const [power, setPower, powerStr, onPowerBlur] = useNumInput(20, {
    int: false,
    min: 0,
    max: 100,
  })
  const [feathering, setFeathering, featheringStr, onFeatheringBlur] =
    useNumInput(0, {
      int: false,
      min: 0,
      max: 20,
    })
  const powerRef = useRef(power)
  const featheringRef = useRef(feathering)
  useEffect(() => {
    powerRef.current = power
  }, [power])
  useEffect(() => {
    featheringRef.current = feathering
  }, [feathering])
  async function onSave(): Promise<void> {
    const hideloading = showLoading()
    try {
      const res = await imageFilter(
        allFrameList,
        canvasSize.width,
        canvasSize.height,
        (ctx, index) => {
          filter(ctx)
          hideloading.setProgress((index / allFrameList.length) * 100)
        }
      )
      onUpdate(res)
    } catch (e) {
      console.error(e)
    } finally {
      hideloading()
    }
  }

  return (
    <div className="RemoveBgModal-component">
      <div className={`RemoveBgModal ${show ? 'show' : ''}`}>
        <div className="top">
          <div className="title">
            <span>{t('removeBackground')}</span>
          </div>
          <ripple-button className="remove" onClick={onHide}>
            <RemoveSvg />
          </ripple-button>
        </div>
        <div className="center-box">
          <div className="canvas-view">
            <CustomCanvas className="canvas" ref={canvasRef}></CustomCanvas>
          </div>

          <div className="input-box">
            <div className="label">
              <label>{t('imageType')}</label>
            </div>
            <div
              style={{
                display: 'flex',
                alignItems: 'center',
                gap: 5,
              }}>
              {removeMode.map((item) => {
                return (
                  <ripple-button
                    key={item.value}
                    className={`mode ${mode == item.value ? 'active' : ''}`}
                    onClick={() => {
                      setMode(item.value)
                    }}>
                    {t(item.label)}
                  </ripple-button>
                )
              })}
            </div>
          </div>
          <div className="input-box">
            <div className="label">
              <label>{t('removeBackground')}</label>
            </div>
            <div
              style={{
                display: 'flex',
                alignItems: 'center',
                gap: 5,
              }}>
              <ripple-button
                className="color-input"
                onClick={async () => {
                  // @ts-ignore
                  const eyeDropper = new EyeDropper()
                  const value = await eyeDropper.open()
                  setColor(value.sRGBHex)
                }}
                style={{
                  background: color,
                }}></ripple-button>
              <span>#</span>

              <input
                type="text"
                className="input"
                value={color.substring(1)}
                onChange={(e) => {
                  let value = e.target.value
                  value = value.replace(/[^0-9a-fA-F]/g, '')
                  if (value.length > 6) {
                    value = value.substring(0, 6)
                  }
                  setColor(`#${value}`)
                }}
              />
            </div>
          </div>

          <div className="input-box">
            <div className="label">
              <label>{t('intensity')}</label>
            </div>
            <div
              style={{
                display: 'flex',
                alignItems: 'center',
                gap: 5,
              }}>
              <input
                type="range"
                style={{
                  width: 150,
                }}
                onChange={(e) => {
                  setPower(e.target.value)
                }}
                step={0.02}
                min={0}
                max={100}
                value={power}></input>
              {/* {power} */}
              <input
                type="number"
                style={{
                  width: 60,
                }}
                className="input"
                value={powerStr}
                onChange={(e) => setPower(e.target.value)}
                onBlur={onPowerBlur}
              />
            </div>
          </div>
          <div className="input-box">
            <div className="label">
              <label>{t('边缘羽化')}</label>
            </div>
            <div
              style={{
                display: 'flex',
                alignItems: 'center',
                gap: 5,
              }}>
              <input
                type="range"
                style={{
                  width: 150,
                }}
                onChange={(e) => {
                  setFeathering(e.target.value)
                }}
                step={0.02}
                min={0}
                max={20}
                value={featheringStr}></input>
              {/* {power} */}
              <input
                type="number"
                style={{
                  width: 60,
                }}
                className="input"
                value={featheringStr}
                onChange={(e) => setFeathering(e.target.value)}
                onBlur={onFeatheringBlur}
              />
            </div>
          </div>
        </div>
        <ripple-button
          style={{
            marginLeft: 'auto',
            background: 'var(--primary-color)',
            color: 'white',
            width: 'fit-content',
            padding: '8px 10px',
          }}
          onClick={onSave}>
          {t('saveChanges')}
        </ripple-button>
      </div>
      <div className={`mask ${show ? 'show' : ''}`} onClick={onHide}></div>
    </div>
  )
}

export default RemoveBgModal
